//
//  ZDEmojiPackage.swift
//  ZDEmojiKeyBoard
//
//  Created by Apple on 15/11/4.
//  Copyright © 2015年 itcast. All rights reserved.
//

import UIKit

/// 表情包模型
class ZDEmojiPackage: NSObject {

    //MARK: 属性
    ///记录表情包得文件名
    var id: String?
    
    ///记录表情包的名字
    var group_name_cn: String?
    
    ///保存表情模型数组
    var emoticons: [ZDEmoji]?
    
    private static let emojiBundlePath = NSBundle.mainBundle().bundlePath + "/Emoticons.bundle"
    
    
    //MARK: - 构造方法 不需要写func
    init(id: String?) {
        
        self.id = id
    }
    
    //定义属性 缓存 表情包数组
    static let emojiPackages = ZDEmojiPackage.loadEmojiPackages()
    
    
    ///增加表情到最近表情包
    class func updateRecentWithEmoji(emoji: ZDEmoji) {
        
        if emoji.removeBtn {
        
            return
        }
    
        //emoji被选中的次数加1
        emoji.times++
        
        //取出最近表情包
        guard let recentEmojiPackage = emojiPackages?.first else {
        
            return
        }
        
        //移除删除按钮
        let removeBtnEmoji = recentEmojiPackage.emoticons!.removeLast()
        
        var emojis = recentEmojiPackage.emoticons!
        
        //如果emojis数组中没有当前emoji，就添加  避免重复添加
        if !emojis.contains(emoji) {
        
            emojis.append(emoji)
        }
        
        //对emojis数组中的表情按选中次数降序排序
        emojis = emojis.sort { (e1, e2) -> Bool in
            
            return e1.times > e2.times
        }
        
        //添加一个 排序后就删除一个排在最后的emoji  保证最近表情包 永远都只有20个表情
        if !recentEmojiPackage.emoticons!.contains(emoji) {   //删除的条件是 只有添加时才删除
            
            emojis.removeLast()
        }
        
        //最后再添加最后一个删除按钮
        emojis.append(removeBtnEmoji)
        
        //重新赋值表情数组  更新
        emojiPackages?.first!.emoticons = emojis
        
//        print(emojiPackages?.first!.emoticons)
//        print(emojiPackages?.first!.emoticons?.count)
    }

    
    //MARK: - 方法
    private class func loadEmojiPackages() -> [ZDEmojiPackage]? {
        
        //打印发现每次呼出键盘都会加载表情包 影响性能 应该缓存
        print("加载表情包")
        
        let plistPath = emojiBundlePath + "/emoticons.plist"
    
        let dict = NSDictionary(contentsOfFile: plistPath)!
        
        let packages = dict["packages"] as! [[String: AnyObject]]
        
        var emojiPackages = [ZDEmojiPackage]()
        
        //将最近表情包 添加到表情包数组中
        emojiPackages.append(creatRecentEmojiPackage())
        
        for dict in packages {
        
            let id = dict["id"] as? String
            
            //创建表情包
            let emojiPackage = ZDEmojiPackage(id: id)
    
            //加载emoji表情数组
            emojiPackage.emoticons = emojiPackage.loadEmojis()
            
//            print(emojiPackage.emoticons?.count)
            
//            print("emojiPackage:\(emojiPackage)")
            
            emojiPackages.append(emojiPackage)
        }
        
        return emojiPackages
    }
    
    
    //加载emoji表情
    func loadEmojis() -> [ZDEmoji]? {
    
        let emojiPlistPath = ZDEmojiPackage.emojiBundlePath + "/\(id!)" + "/info.plist"
        
//        print(emojiPlistPath)
    
        let dict = NSDictionary(contentsOfFile: emojiPlistPath)!
        
        group_name_cn = dict["group_name_cn"] as? String
        
        let emoticons = dict["emoticons"] as! [[String: String]]
        
        var emojis = [ZDEmoji]()
        
        var index = 0
        
        for dict in emoticons {
            
            //字典转模型 并添加到模型数组中
            emojis.append(ZDEmoji(id: id!, dict: dict))
    
//            print("emoji:\(emoji)")
            
            index++
            
            if index == 20 {
            
                //添加一个删除按钮
                emojis.append(ZDEmoji(removeBtn: true))
                
                index = 0
            }
        }
        
        //不足一页的 添加空的emoji模型补齐
        emojis = appendEmptyEmoji(emojis)
        
        return emojis
    }
    
    
    ///添加空的emoji模型
    private func appendEmptyEmoji(var emojis: [ZDEmoji]) -> [ZDEmoji] {
    
        let count = emojis.count % 21
        
        if count > 0 || emojis.count == 0 {
        
            for _ in count..<20 {
            
                emojis.append(ZDEmoji(removeBtn: false))
            }
            
            emojis.append(ZDEmoji(removeBtn: true))
        }
        
        return emojis
    }
    
    
    ///手动创建“最近”表情包
    class private func creatRecentEmojiPackage() -> ZDEmojiPackage {
    
        //手动创建最近表情包
        let recentPackage = ZDEmojiPackage(id: nil)
        
        //设置表情包得名字
        recentPackage.group_name_cn = "最近"
        
        //初始化表情数组
        recentPackage.emoticons = [ZDEmoji]()
        
        //最近表情包中默认是20个空模型 加 1个删除模型
        recentPackage.emoticons = recentPackage.appendEmptyEmoji(recentPackage.emoticons!)
        
        return recentPackage
    }
    
    
    override var description: String {
    
        return "\n\t\t表情包：id:\(id), group_name_cn:\(group_name_cn), emoticons:\(emoticons)"
    }
}



/// emoji表情模型
class ZDEmoji: NSObject {

    //MARK: - 属性
    ///上传到服务器的字段
    var chs: String?
    
    ///图片名称
    var png: String? {
    
        didSet {
            
            if let imagePath = png {
            
                let pngPath = ZDEmojiPackage.emojiBundlePath + "/\(id!)" + "/\(imagePath)"
                
                self.pngPath = pngPath
            }
            else {
            
                self.pngPath = nil
            }
        }
    }
    
    ///系统默认emoji字段
    var code: String? {
    
        didSet {
        
            if let emojiCode = code {
            
                emojiString = getEmojiString(emojiCode)
            }
            else {
            
                emojiString = nil
            }
        }
    }
    
    ///图片路径
    var pngPath: String?
    
    ///记录表情包得文件名
    var id: String?
    
    ///默认emoji字段转换后的字符串
    var emojiString: String?
    
    ///是否是删除按钮
    var removeBtn: Bool = false
    
    ///记录表情被选中的次数
    var times: Int = 0
    
    
    init(removeBtn: Bool) {
        
        super.init()
        
        self.removeBtn = removeBtn
    }
    
    
    //MARK: - 字典转模型
    init(id: String, dict: [String: String]) {
        
        super.init()
        
        self.id = id
        
        setValuesForKeysWithDictionary(dict)
    }
    
    override func setValue(value: AnyObject?, forUndefinedKey key: String) { }
    
    
    override var description: String {
    
        return "\n\t\t表情模型：chs:\(chs), png:\(png), code:\(code), emojiString:\(emojiString), removeBtn:\(removeBtn), times:\(times)"
    }
    
    
    private func getEmojiString(code: String) -> String {
    
        // 扫描器
        let scanner = NSScanner(string: code)
        
        // 存储扫描结果
        // UnsafeMutablePointer<UInt32>: UInt32类型的可变指针
        var value: UInt32 = 0
        
        scanner.scanHexInt(&value)
        
//        print("扫描结果:\(value)")
        
        let c = Character(UnicodeScalar(value))
        
        let str = String(c)
        
        return str
    }
    
    ///将表情模型转成带表情图片的属性文本
    func emojiToAttributeString(font: UIFont) -> NSAttributedString {
    
        guard let imagePath = pngPath else {
        
            return NSAttributedString(string: "")
        }
        
        //取出表情图片
        let image = UIImage(contentsOfFile: imagePath)
        
        //创建附件
        let attachment = ZDTextAttachment()
        //保存图片对应的字段
        attachment.name = chs
        
        //设置附件的图片为表情图片
        attachment.image = image;
        
        //获取线高
        let height = font.lineHeight ?? 10
        
        //设置附件图片的大小
        attachment.bounds = CGRect(x: 0, y: -height * 0.25, width: height, height: height)
        
        //创建带附件的属性文本
        let attributeStr = NSMutableAttributedString(attributedString: NSAttributedString(attachment: attachment))
        
        //设置表情属性文本的字体 ———— 解决重复输入表情图片时，后面的表情图片变小的bug(后面输入的属性文本font参考其前一个属性文本，如果没有设置就是默认值)
        attributeStr.addAttribute(NSFontAttributeName, value: font, range: NSRange(location: 0, length: 1))
        
        return attributeStr
    }
    
    //根据表情文本查找对应的表情模型
    class func emojiStringToEmoji(emojiString: String) -> ZDEmoji? {
        
        var emoji: ZDEmoji?
        
        //遍历所有表情包
        for package in ZDEmojiPackage.emojiPackages! {
            
            //获取表情包过滤
            let result = package.emoticons?.filter({ (e1) -> Bool in
                
                //满足相等条件的元素会放到数组中返回
                return e1.chs == emojiString
            })
            
            emoji = result?.first
            
            //有结果就不需要再遍历
            if emoji != nil {
                
                break
            }
        }
        
        return emoji
    }
    
    ///将表情字符串转换为对应的带表情图片的属性文本
    class func emojiStringToEmojiAttributeString(emojiString: String, font: UIFont) -> NSAttributedString {
        
        /*
        表情字符串转换为表情图片
        1.解析字符串中表情文本
        2.根据表情文本找到对应的表情模型(表情模型里面有表情图片)
        3.将表情模型转成带表情图片的属性文本
        4.将表情文本替换成带表情图片的属性文本
        */
        
        let pattern = "\\[.*?\\]"
        
        let regular = try! NSRegularExpression(pattern: pattern, options: NSRegularExpressionOptions.DotMatchesLineSeparators)
        
        //匹配
        let results = regular.matchesInString(emojiString, options: NSMatchingOptions(rawValue: 0), range: NSRange(location: 0, length: emojiString.characters.count))
        
        //        //遍历匹配结果
        //        for result in results {
        //
        //            let range = result.range
        //
        //            print(range)
        //        }
        
        //将传进来的字符串转换成属性文本
        let attributeStr = NSMutableAttributedString(string: emojiString)
        
        //反向替换
        var count = results.count
        
        while count > 0 {
            
            //从最后开始获取
            let result = results[--count]
            
            let range = result.range
            
//            print(range)
            
            //截取对应的表情文本
            let emojiStr = (emojiString as NSString).substringWithRange(range)
            
            //            print(emojiStr)
            //根据表情文本查找表情模型
            if let emoji = ZDEmoji.emojiStringToEmoji(emojiStr) {
                
                //                print(emoji)
                //将表情模型转换成带表情图片的属性文本
                let attrString = emoji.emojiToAttributeString(font)
                
                //将传进来的字符串中的表情文本 替换成 属性文本
                attributeStr.replaceCharactersInRange(range, withAttributedString: attrString)
            }
        }
        
        return attributeStr
    }

}